import { memo, useState, useCallback, useMemo } from 'react'
import type { FC } from 'react'
import { Environment, ContactShadows, Text, Instances, Instance, Html } from '@react-three/drei'
import { Vector3 } from 'three'
import { MeshStandardMaterial } from 'three'

interface DeviceStatus {
  name: string
  type: string
  location: string
  status: 'online' | 'offline' | 'maintenance'
  lastUpdate: string
}

interface BuildingProps {
  position: [number, number, number]
  size: [number, number, number]
  color: string
  name: string
  onClick?: () => void
  isHighlighted?: boolean
  devices?: DeviceStatus[]
}

// 预定义几何体和材质
const BuildingGeometry = memo(() => <boxGeometry />)
BuildingGeometry.displayName = 'BuildingGeometry'

const StatusIndicator: FC<{ status: DeviceStatus }> = memo(({ status }) => {
  const color = useMemo(() => {
    switch (status.status) {
      case 'online':
        return '#52c41a'
      case 'offline':
        return '#ff4d4f'
      case 'maintenance':
        return '#faad14'
      default:
        return '#d9d9d9'
    }
  }, [status.status])

  return (
    <mesh position={[0.5, 0.5, 0.5]} scale={0.2}>
      <sphereGeometry args={[1, 16, 16]} />
      <meshStandardMaterial color={color} emissive={color} emissiveIntensity={0.5} />
    </mesh>
  )
})

StatusIndicator.displayName = 'StatusIndicator'

const DeviceInfo: FC<{ device: DeviceStatus }> = memo(({ device }) => {
  return (
    <Html position={[0, 1, 0]} center style={{ pointerEvents: 'none' }}>
      <div style={{
        background: 'rgba(0, 0, 0, 0.8)',
        color: 'white',
        padding: '8px',
        borderRadius: '4px',
        fontSize: '12px',
        whiteSpace: 'nowrap'
      }}>
        <div>{device.name}</div>
        <div>状态: {device.status === 'online' ? '在线' : device.status === 'offline' ? '离线' : '维护中'}</div>
        <div>更新: {device.lastUpdate}</div>
      </div>
    </Html>
  )
})

DeviceInfo.displayName = 'DeviceInfo'

const Building: FC<BuildingProps> = memo(({ 
  position,
  size,
  color,
  name,
  onClick,
  isHighlighted = false,
  devices = []
}) => {
  const [hovered, setHovered] = useState(false)
  const [showDeviceInfo, setShowDeviceInfo] = useState<string | null>(null)
  
  const material = useMemo(() => ({
    color: isHighlighted || hovered ? '#ff0000' : color,
    roughness: 0.2,
    metalness: 0.8,
    envMapIntensity: 1,
    emissive: isHighlighted || hovered ? '#ff0000' : '#000000',
    emissiveIntensity: isHighlighted || hovered ? 0.2 : 0
  }), [isHighlighted, hovered, color])
  
  const scale = useMemo(() => new Vector3(...size), [size])
  
  return (
    <group position={position}>
      <mesh
        onPointerOver={() => setHovered(true)}
        onPointerOut={() => setHovered(false)}
        onClick={onClick}
        castShadow
        receiveShadow
        scale={scale}
      >
        <BuildingGeometry />
        <meshStandardMaterial {...material} />
      </mesh>
      <Text
        position={[0, size[1] + 0.5, 0]}
        fontSize={0.5}
        color="white"
        anchorX="center"
        anchorY="middle"
        maxWidth={2}
        textAlign="center"
        outlineWidth={0.1}
        outlineColor="#000000"
      >
        {name}
      </Text>
      {devices.map((device, index) => (
        <group key={device.name} position={[
          (index % 2) * 1 - 0.5,
          Math.floor(index / 2) * 1,
          size[2] / 2
        ]}>
          <StatusIndicator status={device} />
          {showDeviceInfo === device.name && (
            <DeviceInfo device={device} />
          )}
          <mesh
            scale={0.3}
            position={[0.5, 0.5, 0.5]}
            onPointerEnter={() => setShowDeviceInfo(device.name)}
            onPointerLeave={() => setShowDeviceInfo(null)}
          >
            <sphereGeometry args={[1, 16, 16]} />
            <meshStandardMaterial opacity={0} transparent />
          </mesh>
        </group>
      ))}
    </group>
  )
})

Building.displayName = 'Building'

const Ground: FC = memo(() => {
  const material = useMemo(() => ({
    color: "#111111",
    roughness: 0.4,
    metalness: 0.6,
    envMapIntensity: 1
  }), [])

  return (
    <>
      <mesh rotation={[-Math.PI / 2, 0, 0]} position={[0, -0.5, 0]} receiveShadow>
        <planeGeometry args={[200, 200]} />
        <meshStandardMaterial {...material} />
      </mesh>
      <ContactShadows
        position={[0, -0.49, 0]}
        opacity={0.4}
        scale={200}
        blur={2}
        far={40}
        resolution={512}
        color="#000000"
      />
    </>
  )
})

Ground.displayName = 'Ground'

// 使用 Instances 优化道路渲染
const Roads: FC = memo(() => {
  const roadMaterial = useMemo(() => ({
    color: "#333333",
    roughness: 0.3,
    metalness: 0.7,
    envMapIntensity: 1
  }), [])

  return (
    <Instances>
      <planeGeometry args={[4, 40]} />
      <meshStandardMaterial {...roadMaterial} />
      <Instance 
        rotation={[-Math.PI / 2, 0, 0]} 
        position={[0, -0.48, 0]} 
      />
      <Instance 
        rotation={[-Math.PI / 2, Math.PI / 2, 0]} 
        position={[0, -0.48, 0]} 
      />
    </Instances>
  )
})

Roads.displayName = 'Roads'

const ParkScene: FC = memo(() => {
  const [selectedBuilding, setSelectedBuilding] = useState<string | null>(null)

  const mockDevices: Record<string, DeviceStatus[]> = useMemo(() => ({
    '办公楼A': [
      { name: '主入口闸机', type: '闸机', location: 'A区入口', status: 'online', lastUpdate: '2024-01-10' },
      { name: '环境传感器', type: '传感器', location: 'D区办公室', status: 'online', lastUpdate: '2024-01-12' }
    ],
    '研发中心': [
      { name: '消防报警器', type: '报警器', location: 'E区仓库', status: 'maintenance', lastUpdate: '2024-01-15' }
    ],
    '数据中心': [
      { name: '监控摄像头01', type: '摄像头', location: 'C区楼梯', status: 'offline', lastUpdate: '2024-01-05' }
    ],
    '会议中心': [
      { name: '停车场闸机', type: '闸机', location: 'B区停车场', status: 'online', lastUpdate: '2024-01-06' }
    ]
  }), [])

  const buildings = useMemo(() => [
    { 
      position: [-15, 3, -15] as [number, number, number], 
      size: [8, 12, 8] as [number, number, number], 
      color: '#4a90e2',
      name: '办公楼A',
      devices: mockDevices['办公楼A']
    },
    { 
      position: [15, 3, -15] as [number, number, number], 
      size: [8, 9, 8] as [number, number, number], 
      color: '#50c878',
      name: '研发中心',
      devices: mockDevices['研发中心']
    },
    { 
      position: [-15, 3, 15] as [number, number, number], 
      size: [8, 15, 8] as [number, number, number], 
      color: '#deb887',
      name: '数据中心',
      devices: mockDevices['数据中心']
    },
    { 
      position: [15, 3, 15] as [number, number, number], 
      size: [8, 6, 8] as [number, number, number], 
      color: '#cd853f',
      name: '会议中心',
      devices: mockDevices['会议中心']
    },
  ], [mockDevices])

  const facilities = useMemo(() => [
    { position: [0, 1.5, -20] as [number, number, number], size: [3, 3, 3] as [number, number, number], color: '#d3d3d3', name: '门卫室' },
    { position: [-20, 1.5, 0] as [number, number, number], size: [3, 3, 3] as [number, number, number], color: '#d3d3d3', name: '配电室' },
    { position: [20, 1.5, 0] as [number, number, number], size: [3, 3, 3] as [number, number, number], color: '#d3d3d3', name: '监控室' },
    { position: [0, 1.5, 20] as [number, number, number], size: [3, 3, 3] as [number, number, number], color: '#d3d3d3', name: '收发室' },
  ], [])

  const handleBuildingClick = useCallback((name: string) => {
    setSelectedBuilding(prev => prev === name ? null : name)
  }, [])

  return (
    <>
      <Environment preset="city" />
      <Ground />
      <Roads />

      {buildings.map((building, index) => (
        <Building
          key={`building-${index}`}
          {...building}
          onClick={() => handleBuildingClick(building.name)}
          isHighlighted={selectedBuilding === building.name}
        />
      ))}

      {facilities.map((facility, index) => (
        <Building
          key={`facility-${index}`}
          {...facility}
          onClick={() => handleBuildingClick(facility.name)}
          isHighlighted={selectedBuilding === facility.name}
        />
      ))}
    </>
  )
})

ParkScene.displayName = 'ParkScene'

export default ParkScene 